using Abp.Domain.Entities.Auditing;
using Abp.Extensions;
using Abp.Runtime.Caching;
using Abp.Runtime.Session;
using Abp.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yozeev.BusinessLogic;
using Yozeev.BusinessLogic.DomainService;
using Yozeev.Models;
using Yozeev.SystemConfig;
using Yozeev.SystemConfig.BasicConfig.DomainService;
using Yozeev.UserManagerment.Users;

namespace Yozeev.Controllers
{
    public abstract class CommonController : YozeevControllerBase
    {
        public readonly SourceManager _sourceManager;
        public readonly ScheduleManager _scheduleManager;
        public readonly PayMethodManager _payMethodManager;
        public readonly TicketPriceManager _ticketPriceManager;
        public readonly CustomerManager _customerManager;
        public readonly TravelAgencyManager _travelManager;

        public readonly UserManager _userManager;
        private ICacheManager _cacheManager;
        protected CommonController(SourceManager sourceManager
            , ScheduleManager scheduleManager
            , PayMethodManager payMethodManager
            , ICacheManager cacheManager
            , TicketPriceManager ticketPriceManager
            , CustomerManager customerManager
            , UserManager userManager
            , TravelAgencyManager travelManager
            )
        {
            _sourceManager = sourceManager;
            _scheduleManager = scheduleManager;
            _payMethodManager = payMethodManager;
            _cacheManager = cacheManager;
            _ticketPriceManager = ticketPriceManager;
            _customerManager = customerManager;
            _userManager = userManager;
            _travelManager = travelManager;
        }

        #region

        /// <summary>
        ///     返回当前用户信息
        /// </summary>
        /// <returns></returns>
        protected virtual async Task<User> GetCurrentUserAsync()
        {
            var user = await _userManager.FindByIdAsync(AbpSession.GetUserId().ToString());
            if (user == null) throw new Exception("当前用户不存在!");
            return user;
        }
        /// <summary>
        /// 返回当前用户信息--非异步
        /// </summary>
        /// <returns></returns>
        protected virtual User GetCurrentUser()
        {
            return AsyncHelper.RunSync(GetCurrentUserAsync);
        }
        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <returns></returns>
        protected ICache GetICache() 
        {
            var cacheKey = CacheConsts.HostApi_TokenAuth_Authenticate;
            if (AbpSession.TenantId.HasValue)
            {
                cacheKey = $"{AbpSession.TenantId}-{CacheConsts.HostApi_TokenAuth_Authenticate}";
            }
            return _cacheManager.GetCache(cacheKey);
        }
        /// <summary>
        /// 获取缓存中的数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="cacheName">key</param>
        /// <returns></returns>
        protected T getCacheT<T>(string cacheName)
        {
            //从缓存中获取售票源
            var cache = GetICache();
            return cache.GetOrDefault<string, T>(cacheName);
            
        }
        /// <summary>
        /// 获取售票源列表
        /// </summary>
        /// <returns></returns>
        protected List<PayMethod> GetPayMethodList()
        {
            List<PayMethod> list = null;
            //从缓存中获取售票源
            list = getCacheT<List<PayMethod>>("PayMethodList");
            if (list == null)
            {
                list = _payMethodManager.GetPayMethodList();
                //将售票源保存进缓存中
                GetICache().SetAsync("PayMethodList", list);
            }
            return list;
        }
        /// <summary>
        /// 获取售票源列表
        /// </summary>
        /// <returns></returns>
        protected List<Source> GetSourceList()
        {
            List<Source> sourceList = null;
            //从缓存中获取售票源
            sourceList = getCacheT<List<Source>>( "SourceList");
            if (sourceList == null)
            {
                sourceList = _sourceManager.GetSourceList();
                //将售票源保存进缓存中
                GetICache().SetAsync("SourceList", sourceList);
            }
            return sourceList;
        }
        /// <summary>
        /// 缓存中获取排班
        /// </summary>
        /// <returns></returns>
        protected Schedule GetSchedule(Guid scheduleId)
        {
            Schedule schedule = null;
            //从缓存中获取排班
            schedule = getCacheT<Schedule>(scheduleId.ToString());
            if (schedule == null)
            {
                schedule = _scheduleManager.GetScheduleById(scheduleId);
                //将售票源保存进缓存中
                GetICache().SetAsync(scheduleId.ToString(), schedule);
            }
            return schedule;
        }
        /// <summary>
        /// 创建航班缓存
        /// </summary>
        /// <returns></returns>
        protected List<Schedule> GetScheduleList()
        {
            var list = _scheduleManager.GetScheduleList();
            //将航班列表保存进缓存中
            GetICache().SetAsync("ScheduleList", list, TimeSpan.MaxValue);
            return list;
        }
        /// <summary>
        /// 获取票价列表
        /// </summary>
        /// <returns></returns>
        protected List<TicketPrice> GetTicketPriceList()
        {
            List<TicketPrice> ticketPriceList = null;
            //从缓存中获取票价
            ticketPriceList = getCacheT<List<TicketPrice>>("TicketPriceList");
            if (ticketPriceList == null)
            {
                ticketPriceList = _ticketPriceManager.GetTicketPriceList();
                //将票价保存进缓存中
                GetICache().SetAsync("TicketPriceList", ticketPriceList);
            }
            return ticketPriceList;
        }
        /// <summary>
        /// 根据票价Id查找缓存中的票价
        /// </summary>
        /// <param name="ticketPriceId"></param>
        /// <returns></returns>
        protected TicketPrice GetTicketPriceByCache(Guid ticketPriceId)
        {
            TicketPrice ticketPrice = null;
            //从缓存中获取售票源
            ticketPrice = getCacheT<TicketPrice>(ticketPriceId.ToString());
            if (ticketPrice == null)
            {
                ticketPrice = _ticketPriceManager.GetTicketPriceList().FirstOrDefault(m => m.Id == ticketPriceId);
                //将售票源保存进缓存中
                GetICache().SetAsync(ticketPriceId.ToString(), ticketPrice);
            }
            return ticketPrice;
        }
        protected List<Customer> GetCustomerByIds(Guid[] guids)
        {
            var list = _customerManager.GetCustomersByIds(guids).Result;
            return list;
        }

        protected Customer GetCustomerById(Guid Id)
        {
            var list = _customerManager.GetCustomerById(Id).Result;
            return list;
        }
        /// <summary>
        /// 更新航班数据
        /// </summary>
        /// <param name="schedule"></param>
        protected void UpdateSchedule(Schedule schedule)
        {
            _scheduleManager.UpdateSchedule(schedule);
        }
        /// <summary>
        /// 缓存中查询是否有剩余票，并设置剩余票数量
        /// </summary>
        /// <param name="Schedule">航班</param>
        /// <param name="TotalQuantity">购票数</param>
        /// <param name="WarePosition">仓位</param>
        protected long IsExistenTicket(Schedule Schedule, long TotalQuantity,WareHousePosition WarePosition)
        {
            if(Schedule.EndTime<DateTime.Now)
            {
                throw new Exception("航班" + Schedule.ScheduleCode + "售票结束");
            }
            long surplusQuantity = 0;
            switch(WarePosition)
            {
                case WareHousePosition.StandradPosition:
                    { 
                        surplusQuantity = Schedule.StandardSurplusNum;
                        if (surplusQuantity < TotalQuantity)
                        {
                            throw new Exception("航班" + Schedule.ScheduleCode + "已无剩余票");
                        }
                        //重新设置剩余票数
                        Schedule.StandardSurplusNum -= TotalQuantity;
                        break;
                    }
                case WareHousePosition.VIPPosition:
                    {
                        surplusQuantity = Schedule.VIPSurplusNum;
                        if (surplusQuantity < TotalQuantity)
                        {
                            throw new Exception("航班" + Schedule.ScheduleCode + "已无剩余票");
                        }
                        //重新设置剩余票数
                        Schedule.VIPSurplusNum -= TotalQuantity;
                        break;
                    }
                case WareHousePosition.CompartmentPosotion:
                    {
                        surplusQuantity = Schedule.CompartmentSurplusNum;
                        //重新设置剩余票数
                        Schedule.VIPSurplusNum -= TotalQuantity;
                        break;
                    }
            }
            //重新设置剩余票数
            if (TotalQuantity != 0)
            {
                Schedule.SurplusQuantity -= TotalQuantity;
                TimeSpan slidingExpireTime = Schedule.EndTime - DateTime.Now;
                GetICache().SetAsync(Schedule.Id.ToString(), Schedule, slidingExpireTime);
                UpdateSchedule(Schedule);
            }
            return surplusQuantity - TotalQuantity;
        }
        /// <summary>
        /// 判断暂存订单创建提交数据是否有欠缺 
        /// </summary>
        /// <returns></returns>
        protected ActivityTemp IsGetActivityTemp(CreateActivityModel createActivityModel)
        {
            decimal Discount = 1;
            if (createActivityModel.PayMethodId.ToString().IsNullOrWhiteSpace())
                throw new Exception("支付方式不能为空");
            var payMethod = GetPayMethodList().FirstOrDefault(m => m.Id == createActivityModel.PayMethodId);
            if (payMethod == null)
                throw new Exception("查无该支付方式");

            if (createActivityModel.SourceId.ToString().IsNullOrWhiteSpace())
                throw new Exception("订单来源不能为空");
            var source = GetSourceList().FirstOrDefault(m => m.Id == createActivityModel.SourceId);
            if (source == null)
                throw new Exception("查无该订单来源");

            if (createActivityModel.activityDetails.Count <= 0)
                throw new Exception("购票数不能为零");

            if (AbpSession.UserId == null)
            {
                throw new Exception("创建人不能为空");
            }

            var activity = new ActivityTemp()
            {
                PayMethodId = (Guid)createActivityModel.PayMethodId,
                PayMethod = payMethod,
                SourceId = (Guid)createActivityModel.SourceId,
                Source = source,
                ActivityDetails = new List<ActivityTempDetail>(),
                CreatorUserId = (long)AbpSession.UserId,
                OrderType = createActivityModel.OrderType,
            };
            if (!createActivityModel.Remark.IsNullOrWhiteSpace())
                activity.Remark = createActivityModel.Remark;
            if (!createActivityModel.VoucherNo.IsNullOrWhiteSpace())
                activity.VoucherNo = createActivityModel.VoucherNo;
            if (activity.OrderType == Abp.Domain.Entities.Auditing.OrderTypeEnum.OrderTypeTravelAgency)
            {
                activity.TravelAgencyId = createActivityModel.TravelAgencyId;
                var travel = _travelManager.GetEntityById((Guid)createActivityModel.TravelAgencyId).Result;
                Discount = travel.Discount;
            }
            if (!createActivityModel.OpenId.IsNullOrWhiteSpace())
                activity.OpenId = createActivityModel.OpenId;
            createActivityModel.activityDetails.ForEach(m => {
                if (m.ticketPriceId.ToString().IsNullOrWhiteSpace())
                    throw new Exception("金额不能为空");
                var ticketPrice = GetTicketPriceByCache(m.ticketPriceId);
                if (ticketPrice == null)
                    throw new Exception("查无该票价信息");

                if (m.ScheduleId.ToString().IsNullOrWhiteSpace())
                    throw new Exception("航班不能为空");
                var schedule = GetSchedule(m.ScheduleId);
                if (schedule == null)
                    throw new Exception("查无该航班");
                //查看是否有剩余票
                IsExistenTicket(schedule, m.quantity, ticketPrice.WarePosition);
                activity.ScheduleId = m.ScheduleId;
                if (m.customerId.ToString().IsNullOrWhiteSpace())
                    throw new Exception("游客不能为空");
                var customer = GetCustomerById(m.customerId);
                if (customer == null)
                    throw new Exception("查无该游客");

                createActivityModel.TotalAmount += ticketPrice.Price;
                var activityDetail = new ActivityTempDetail()
                {
                    Customer = customer,
                    TicketPrice = ticketPrice,
                    Quantity = m.quantity,
                    Schedule = schedule,
                };
                activityDetail.TicketPrice.Discount *= Discount;
                activity.ActivityDetails.Add(activityDetail);
            });
            activity.TotalQuantity = createActivityModel.activityDetails.Count;
            activity.TotalAmount = activity.ActivityDetails.Sum(m => m.TicketPrice.Discount * m.TicketPrice.Price * m.Quantity);

            return activity;
        }

        /// <summary>
        /// 根据预留订单填充订单
        /// </summary>
        /// <param name="activityTemp"></param>
        /// <returns></returns>
        protected Activity FillActivityByTemp(ActivityTemp activityTemp,User user=null)
        {
            decimal Discount = 1;
            //判断是否可以提交
            if (activityTemp.PayStatus != PayStatusEnum.NotPay)
                throw new Exception("该预留订单不是未支付状态");
            if (activityTemp.CreationTime.AddMinutes(30) < DateTime.Now)
                throw new Exception("已超过支付时间，不能提交");
            var activity = new Activity()
            {
                PlayDate = activityTemp.PlayDate,
                PayMethodId = activityTemp.PayMethodId,
                PayMethod = activityTemp.PayMethod,
                SourceId = activityTemp.SourceId,
                Source = activityTemp.Source,
                ActivityDetails = new List<ActivityDetail>(),
                CreatorUserId = user == null ? (long)AbpSession.UserId : user.Id,
                OrderType = activityTemp.OrderType,
            };
            if (!activityTemp.Remark.IsNullOrWhiteSpace())
                activity.Remark = activityTemp.Remark;
            if (activity.OrderType == Abp.Domain.Entities.Auditing.OrderTypeEnum.OrderTypeTravelAgency)
            {
                activity.TravelAgencyId = activityTemp.TravelAgencyId;
            }
            activityTemp.ActivityDetails.ToList().ForEach(activityTempDetail => {
                var activityDetail = new ActivityDetail()
                {
                    Schedule = GetSchedule((Guid)activityTempDetail.ScheduleId),
                    Customer = GetCustomerById(activityTempDetail.CustomerId),
                    TicketPrice = GetTicketPriceList().FirstOrDefault(m => m.Id == activityTempDetail.TicketPriceId),
                    Quantity = activityTempDetail.Quantity,
                };
                activity.ActivityDetails.Add(activityDetail);
            });
            activity.TotalQuantity = activityTemp.ActivityDetails.Count;
            activity.TotalAmount = activity.ActivityDetails.Sum(m => m.TicketPrice.Discount * m.TicketPrice.Price * m.Quantity);
            return activity;
        }
        /// <summary>
        /// 校验退票信息
        /// </summary>
        /// <param name="ticketDetailList"></param>
        /// <returns></returns>
        protected List<TicketDetail> CheckRefundList(List<TicketDetail> ticketDetailList)
        {
            //判断该票型是否可以出售
            if (ticketDetailList.Where(m => m.Schedule.StartTime < DateTime.Now).ToList().Count > 0)
                throw new Exception("航班已开始航行");
            if (ticketDetailList.Where(m => m.TicketStatus == TicketStatusEnum.TicketRefund).ToList().Count > 0)
                throw new Exception("存在已退票数据");
            if (ticketDetailList.Where(m => m.TicketStatus == TicketStatusEnum.Used).ToList().Count > 0)
                throw new Exception("存在已使用的票");
            if (AbpSession.UserId == null)
            {
                throw new Exception("创建人不能为空");
            }
            return ticketDetailList;
        }
        #endregion
    }
}
